home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / model.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  43KB  |  1,875 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // models.c -- model loading and caching
  21.  
  22. // models are the only shared resource between a client and server running
  23. // on the same machine.
  24.  
  25. #include "quakedef.h"
  26. #include "r_local.h"
  27.  
  28. model_t    *loadmodel;
  29. char    loadname[32];    // for hunk tags
  30.  
  31. void Mod_LoadSpriteModel (model_t *mod, void *buffer);
  32. void Mod_LoadBrushModel (model_t *mod, void *buffer);
  33. void Mod_LoadAliasModel (model_t *mod, void *buffer);
  34. model_t *Mod_LoadModel (model_t *mod, qboolean crash);
  35.  
  36. byte    mod_novis[MAX_MAP_LEAFS/8];
  37.  
  38. #define    MAX_MOD_KNOWN    256
  39. model_t    mod_known[MAX_MOD_KNOWN];
  40. int        mod_numknown;
  41.  
  42. // values for model_t's needload
  43. #define NL_PRESENT        0
  44. #define NL_NEEDS_LOADED    1
  45. #define NL_UNREFERENCED    2
  46.  
  47. /*
  48. ===============
  49. Mod_Init
  50. ===============
  51. */
  52. void Mod_Init (void)
  53. {
  54.     memset (mod_novis, 0xff, sizeof(mod_novis));
  55. }
  56.  
  57. /*
  58. ===============
  59. Mod_Extradata
  60.  
  61. Caches the data if needed
  62. ===============
  63. */
  64. void *Mod_Extradata (model_t *mod)
  65. {
  66.     void    *r;
  67.     
  68.     r = Cache_Check (&mod->cache);
  69.     if (r)
  70.         return r;
  71.  
  72.     Mod_LoadModel (mod, true);
  73.     
  74.     if (!mod->cache.data)
  75.         Sys_Error ("Mod_Extradata: caching failed");
  76.     return mod->cache.data;
  77. }
  78.  
  79. /*
  80. ===============
  81. Mod_PointInLeaf
  82. ===============
  83. */
  84. mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
  85. {
  86.     mnode_t        *node;
  87.     float        d;
  88.     mplane_t    *plane;
  89.     
  90.     if (!model || !model->nodes)
  91.         Sys_Error ("Mod_PointInLeaf: bad model");
  92.  
  93.     node = model->nodes;
  94.     while (1)
  95.     {
  96.         if (node->contents < 0)
  97.             return (mleaf_t *)node;
  98.         plane = node->plane;
  99.         d = DotProduct (p,plane->normal) - plane->dist;
  100.         if (d > 0)
  101.             node = node->children[0];
  102.         else
  103.             node = node->children[1];
  104.     }
  105.     
  106.     return NULL;    // never reached
  107. }
  108.  
  109.  
  110. /*
  111. ===================
  112. Mod_DecompressVis
  113. ===================
  114. */
  115. byte *Mod_DecompressVis (byte *in, model_t *model)
  116. {
  117.     static byte    decompressed[MAX_MAP_LEAFS/8];
  118.     int        c;
  119.     byte    *out;
  120.     int        row;
  121.  
  122.     row = (model->numleafs+7)>>3;    
  123.     out = decompressed;
  124.  
  125.     if (!in)
  126.     {    // no vis info, so make all visible
  127.         while (row)
  128.         {
  129.             *out++ = 0xff;
  130.             row--;
  131.         }
  132.         return decompressed;        
  133.     }
  134.  
  135.     do
  136.     {
  137.         if (*in)
  138.         {
  139.             *out++ = *in++;
  140.             continue;
  141.         }
  142.     
  143.         c = in[1];
  144.         in += 2;
  145.         while (c)
  146.         {
  147.             *out++ = 0;
  148.             c--;
  149.         }
  150.     } while (out - decompressed < row);
  151.     
  152.     return decompressed;
  153. }
  154.  
  155. byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
  156. {
  157.     if (leaf == model->leafs)
  158.         return mod_novis;
  159.     return Mod_DecompressVis (leaf->compressed_vis, model);
  160. }
  161.  
  162. /*
  163. ===================
  164. Mod_ClearAll
  165. ===================
  166. */
  167. void Mod_ClearAll (void)
  168. {
  169.     int        i;
  170.     model_t    *mod;
  171.  
  172.  
  173.     for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) {
  174.         mod->needload = NL_UNREFERENCED;
  175. //FIX FOR CACHE_ALLOC ERRORS:
  176.         if (mod->type == mod_sprite) mod->cache.data = NULL;
  177.     }
  178. }
  179.  
  180. /*
  181. ==================
  182. Mod_FindName
  183.  
  184. ==================
  185. */
  186. model_t *Mod_FindName (char *name)
  187. {
  188.     int        i;
  189.     model_t    *mod;
  190.     model_t    *avail = NULL;
  191.  
  192.     if (!name[0])
  193.         Sys_Error ("Mod_ForName: NULL name");
  194.         
  195. //
  196. // search the currently loaded models
  197. //
  198.     for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
  199.     {
  200.         if (!strcmp (mod->name, name) )
  201.             break;
  202.         if (mod->needload == NL_UNREFERENCED)
  203.             if (!avail || mod->type != mod_alias)
  204.                 avail = mod;
  205.     }
  206.             
  207.     if (i == mod_numknown)
  208.     {
  209.         if (mod_numknown == MAX_MOD_KNOWN)
  210.         {
  211.             if (avail)
  212.             {
  213.                 mod = avail;
  214.                 if (mod->type == mod_alias)
  215.                     if (Cache_Check (&mod->cache))
  216.                         Cache_Free (&mod->cache);
  217.             }
  218.             else
  219.                 Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
  220.         }
  221.         else
  222.             mod_numknown++;
  223.         strcpy (mod->name, name);
  224.         mod->needload = NL_NEEDS_LOADED;
  225.     }
  226.  
  227.     return mod;
  228. }
  229.  
  230. /*
  231. ==================
  232. Mod_TouchModel
  233.  
  234. ==================
  235. */
  236. void Mod_TouchModel (char *name)
  237. {
  238.     model_t    *mod;
  239.     
  240.     mod = Mod_FindName (name);
  241.     
  242.     if (mod->needload == NL_PRESENT)
  243.     {
  244.         if (mod->type == mod_alias)
  245.             Cache_Check (&mod->cache);
  246.     }
  247. }
  248.  
  249. /*
  250. ==================
  251. Mod_LoadModel
  252.  
  253. Loads a model into the cache
  254. ==================
  255. */
  256. model_t *Mod_LoadModel (model_t *mod, qboolean crash)
  257. {
  258.     unsigned *buf;
  259.     byte    stackbuf[1024];        // avoid dirtying the cache heap
  260.  
  261.     if (mod->type == mod_alias)
  262.     {
  263.         if (Cache_Check (&mod->cache))
  264.         {
  265.             mod->needload = NL_PRESENT;
  266.             return mod;
  267.         }
  268.     }
  269.     else
  270.     {
  271.         if (mod->needload == NL_PRESENT)
  272.             return mod;
  273.     }
  274.  
  275. //
  276. // because the world is so huge, load it one piece at a time
  277. //
  278.     
  279. //
  280. // load the file
  281. //
  282.     buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
  283.     if (!buf)
  284.     {
  285.         if (crash)
  286.             Sys_Error ("Mod_NumForName: %s not found", mod->name);
  287.         return NULL;
  288.     }
  289.     
  290. //
  291. // allocate a new model
  292. //
  293.     COM_FileBase (mod->name, loadname);
  294.     
  295.     loadmodel = mod;
  296.  
  297. //
  298. // fill it in
  299. //
  300.  
  301. // call the apropriate loader
  302.     mod->needload = NL_PRESENT;
  303.  
  304.     switch (LittleLong(*(unsigned *)buf))
  305.     {
  306.     case IDPOLYHEADER:
  307.         Mod_LoadAliasModel (mod, buf);
  308.         break;
  309.         
  310.     case IDSPRITEHEADER:
  311.         Mod_LoadSpriteModel (mod, buf);
  312.         break;
  313.     
  314.     default:
  315.         Mod_LoadBrushModel (mod, buf);
  316.         break;
  317.     }
  318.  
  319.     return mod;
  320. }
  321.  
  322. /*
  323. ==================
  324. Mod_ForName
  325.  
  326. Loads in a model for the given name
  327. ==================
  328. */
  329. model_t *Mod_ForName (char *name, qboolean crash)
  330. {
  331.     model_t    *mod;
  332.  
  333.     mod = Mod_FindName (name);
  334.  
  335.     return Mod_LoadModel (mod, crash);
  336. }
  337.  
  338.  
  339. /*
  340. ===============================================================================
  341.  
  342.                     BRUSHMODEL LOADING
  343.  
  344. ===============================================================================
  345. */
  346.  
  347. byte    *mod_base;
  348.  
  349.  
  350. /*
  351. =================
  352. Mod_LoadTextures
  353. =================
  354. */
  355. void Mod_LoadTextures (lump_t *l)
  356. {
  357.     int        i, j, pixels, num, max, altmax;
  358.     miptex_t    *mt;
  359.     texture_t    *tx, *tx2;
  360.     texture_t    *anims[10];
  361.     texture_t    *altanims[10];
  362.     dmiptexlump_t *m;
  363.  
  364.     if (!l->filelen)
  365.     {
  366.         loadmodel->textures = NULL;
  367.         return;
  368.     }
  369.     m = (dmiptexlump_t *)(mod_base + l->fileofs);
  370.     
  371.     m->nummiptex = LittleLong (m->nummiptex);
  372.     
  373.     loadmodel->numtextures = m->nummiptex;
  374.     loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
  375.  
  376.     for (i=0 ; i<m->nummiptex ; i++)
  377.     {
  378.         m->dataofs[i] = LittleLong(m->dataofs[i]);
  379.         if (m->dataofs[i] == -1)
  380.             continue;
  381.         mt = (miptex_t *)((byte *)m + m->dataofs[i]);
  382.         mt->width = LittleLong (mt->width);
  383.         mt->height = LittleLong (mt->height);
  384.         for (j=0 ; j<MIPLEVELS ; j++)
  385.             mt->offsets[j] = LittleLong (mt->offsets[j]);
  386.         
  387.         if ( (mt->width & 15) || (mt->height & 15) )
  388.             Sys_Error ("Texture %s is not 16 aligned", mt->name);
  389.         pixels = mt->width*mt->height/64*85;
  390.         tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
  391.         loadmodel->textures[i] = tx;
  392.  
  393.         memcpy (tx->name, mt->name, sizeof(tx->name));
  394.         tx->width = mt->width;
  395.         tx->height = mt->height;
  396.         for (j=0 ; j<MIPLEVELS ; j++)
  397.             tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
  398.         // the pixels immediately follow the structures
  399.         memcpy ( tx+1, mt+1, pixels);
  400.         
  401.         if (!Q_strncmp(mt->name,"sky",3))    
  402.             R_InitSky (tx);
  403.     }
  404.  
  405. //
  406. // sequence the animations
  407. //
  408.     for (i=0 ; i<m->nummiptex ; i++)
  409.     {
  410.         tx = loadmodel->textures[i];
  411.         if (!tx || tx->name[0] != '+')
  412.             continue;
  413.         if (tx->anim_next)
  414.             continue;    // allready sequenced
  415.  
  416.     // find the number of frames in the animation
  417.         memset (anims, 0, sizeof(anims));
  418.         memset (altanims, 0, sizeof(altanims));
  419.  
  420.         max = tx->name[1];
  421.         altmax = 0;
  422.         if (max >= 'a' && max <= 'z')
  423.             max -= 'a' - 'A';
  424.         if (max >= '0' && max <= '9')
  425.         {
  426.             max -= '0';
  427.             altmax = 0;
  428.             anims[max] = tx;
  429.             max++;
  430.         }
  431.         else if (max >= 'A' && max <= 'J')
  432.         {
  433.             altmax = max - 'A';
  434.             max = 0;
  435.             altanims[altmax] = tx;
  436.             altmax++;
  437.         }
  438.         else
  439.             Sys_Error ("Bad animating texture %s", tx->name);
  440.  
  441.         for (j=i+1 ; j<m->nummiptex ; j++)
  442.         {
  443.             tx2 = loadmodel->textures[j];
  444.             if (!tx2 || tx2->name[0] != '+')
  445.                 continue;
  446.             if (strcmp (tx2->name+2, tx->name+2))
  447.                 continue;
  448.  
  449.             num = tx2->name[1];
  450.             if (num >= 'a' && num <= 'z')
  451.                 num -= 'a' - 'A';
  452.             if (num >= '0' && num <= '9')
  453.             {
  454.                 num -= '0';
  455.                 anims[num] = tx2;
  456.                 if (num+1 > max)
  457.                     max = num + 1;
  458.             }
  459.             else if (num >= 'A' && num <= 'J')
  460.             {
  461.                 num = num - 'A';
  462.                 altanims[num] = tx2;
  463.                 if (num+1 > altmax)
  464.                     altmax = num+1;
  465.             }
  466.             else
  467.                 Sys_Error ("Bad animating texture %s", tx->name);
  468.         }
  469.         
  470. #define    ANIM_CYCLE    2
  471.     // link them all together
  472.         for (j=0 ; j<max ; j++)
  473.         {
  474.             tx2 = anims[j];
  475.             if (!tx2)
  476.                 Sys_Error ("Missing frame %i of %s",j, tx->name);
  477.             tx2->anim_total = max * ANIM_CYCLE;
  478.             tx2->anim_min = j * ANIM_CYCLE;
  479.             tx2->anim_max = (j+1) * ANIM_CYCLE;
  480.             tx2->anim_next = anims[ (j+1)%max ];
  481.             if (altmax)
  482.                 tx2->alternate_anims = altanims[0];
  483.         }
  484.         for (j=0 ; j<altmax ; j++)
  485.         {
  486.             tx2 = altanims[j];
  487.             if (!tx2)
  488.                 Sys_Error ("Missing frame %i of %s",j, tx->name);
  489.             tx2->anim_total = altmax * ANIM_CYCLE;
  490.             tx2->anim_min = j * ANIM_CYCLE;
  491.             tx2->anim_max = (j+1) * ANIM_CYCLE;
  492.             tx2->anim_next = altanims[ (j+1)%altmax ];
  493.             if (max)
  494.                 tx2->alternate_anims = anims[0];
  495.         }
  496.     }
  497. }
  498.  
  499. /*
  500. =================
  501. Mod_LoadLighting
  502. =================
  503. */
  504. void Mod_LoadLighting (lump_t *l)
  505. {
  506.     if (!l->filelen)
  507.     {
  508.         loadmodel->lightdata = NULL;
  509.         return;
  510.     }
  511.     loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);    
  512.     memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
  513. }
  514.  
  515.  
  516. /*
  517. =================
  518. Mod_LoadVisibility
  519. =================
  520. */
  521. void Mod_LoadVisibility (lump_t *l)
  522. {
  523.     if (!l->filelen)
  524.     {
  525.         loadmodel->visdata = NULL;
  526.         return;
  527.     }
  528.     loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);    
  529.     memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
  530. }
  531.  
  532.  
  533. /*
  534. =================
  535. Mod_LoadEntities
  536. =================
  537. */
  538. void Mod_LoadEntities (lump_t *l)
  539. {
  540.     if (!l->filelen)
  541.     {
  542.         loadmodel->entities = NULL;
  543.         return;
  544.     }
  545.     loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);    
  546.     memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
  547. }
  548.  
  549.  
  550. /*
  551. =================
  552. Mod_LoadVertexes
  553. =================
  554. */
  555. void Mod_LoadVertexes (lump_t *l)
  556. {
  557.     dvertex_t    *in;
  558.     mvertex_t    *out;
  559.     int            i, count;
  560.  
  561.     in = (void *)(mod_base + l->fileofs);
  562.     if (l->filelen % sizeof(*in))
  563.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  564.     count = l->filelen / sizeof(*in);
  565.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  566.  
  567.     loadmodel->vertexes = out;
  568.     loadmodel->numvertexes = count;
  569.  
  570.     for ( i=0 ; i<count ; i++, in++, out++)
  571.     {
  572.         out->position[0] = LittleFloat (in->point[0]);
  573.         out->position[1] = LittleFloat (in->point[1]);
  574.         out->position[2] = LittleFloat (in->point[2]);
  575.     }
  576. }
  577.  
  578. /*
  579. =================
  580. Mod_LoadSubmodels
  581. =================
  582. */
  583. void Mod_LoadSubmodels (lump_t *l)
  584. {
  585.     dmodel_t    *in;
  586.     dmodel_t    *out;
  587.     int            i, j, count;
  588.  
  589.     in = (void *)(mod_base + l->fileofs);
  590.     if (l->filelen % sizeof(*in))
  591.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  592.     count = l->filelen / sizeof(*in);
  593.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  594.  
  595.     loadmodel->submodels = out;
  596.     loadmodel->numsubmodels = count;
  597.  
  598.     for ( i=0 ; i<count ; i++, in++, out++)
  599.     {
  600.         for (j=0 ; j<3 ; j++)
  601.         {    // spread the mins / maxs by a pixel
  602.             out->mins[j] = LittleFloat (in->mins[j]) - 1;
  603.             out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
  604.             out->origin[j] = LittleFloat (in->origin[j]);
  605.         }
  606.         for (j=0 ; j<MAX_MAP_HULLS ; j++)
  607.             out->headnode[j] = LittleLong (in->headnode[j]);
  608.         out->visleafs = LittleLong (in->visleafs);
  609.         out->firstface = LittleLong (in->firstface);
  610.         out->numfaces = LittleLong (in->numfaces);
  611.     }
  612. }
  613.  
  614. /*
  615. =================
  616. Mod_LoadEdges
  617. =================
  618. */
  619. void Mod_LoadEdges (lump_t *l)
  620. {
  621.     dedge_t *in;
  622.     medge_t *out;
  623.     int     i, count;
  624.  
  625.     in = (void *)(mod_base + l->fileofs);
  626.     if (l->filelen % sizeof(*in))
  627.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  628.     count = l->filelen / sizeof(*in);
  629.     out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);    
  630.  
  631.     loadmodel->edges = out;
  632.     loadmodel->numedges = count;
  633.  
  634.     for ( i=0 ; i<count ; i++, in++, out++)
  635.     {
  636.         out->v[0] = (unsigned short)LittleShort(in->v[0]);
  637.         out->v[1] = (unsigned short)LittleShort(in->v[1]);
  638.     }
  639. }
  640.  
  641. /*
  642. =================
  643. Mod_LoadTexinfo
  644. =================
  645. */
  646. void Mod_LoadTexinfo (lump_t *l)
  647. {
  648.     texinfo_t *in;
  649.     mtexinfo_t *out;
  650.     int     i, j, count;
  651.     int        miptex;
  652.     float    len1, len2;
  653.  
  654.     in = (void *)(mod_base + l->fileofs);
  655.     if (l->filelen % sizeof(*in))
  656.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  657.     count = l->filelen / sizeof(*in);
  658.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  659.  
  660.     loadmodel->texinfo = out;
  661.     loadmodel->numtexinfo = count;
  662.  
  663.     for ( i=0 ; i<count ; i++, in++, out++)
  664.     {
  665.         for (j=0 ; j<8 ; j++)
  666.             out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
  667.         len1 = Length (out->vecs[0]);
  668.         len2 = Length (out->vecs[1]);
  669.         len1 = (len1 + len2)/2;
  670.         if (len1 < 0.32)
  671.             out->mipadjust = 4;
  672.         else if (len1 < 0.49)
  673.             out->mipadjust = 3;
  674.         else if (len1 < 0.99)
  675.             out->mipadjust = 2;
  676.         else
  677.             out->mipadjust = 1;
  678. #if 0
  679.         if (len1 + len2 < 0.001)
  680.             out->mipadjust = 1;        // don't crash
  681.         else
  682.             out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
  683. #endif
  684.  
  685.         miptex = LittleLong (in->miptex);
  686.         out->flags = LittleLong (in->flags);
  687.     
  688.         if (!loadmodel->textures)
  689.         {
  690.             out->texture = r_notexture_mip;    // checkerboard texture
  691.             out->flags = 0;
  692.         }
  693.         else
  694.         {
  695.             if (miptex >= loadmodel->numtextures)
  696.                 Sys_Error ("miptex >= loadmodel->numtextures");
  697.             out->texture = loadmodel->textures[miptex];
  698.             if (!out->texture)
  699.             {
  700.                 out->texture = r_notexture_mip; // texture not found
  701.                 out->flags = 0;
  702.             }
  703.         }
  704.     }
  705. }
  706.  
  707. /*
  708. ================
  709. CalcSurfaceExtents
  710.  
  711. Fills in s->texturemins[] and s->extents[]
  712. ================
  713. */
  714. void CalcSurfaceExtents (msurface_t *s)
  715. {
  716.     float    mins[2], maxs[2], val;
  717.     int        i,j, e;
  718.     mvertex_t    *v;
  719.     mtexinfo_t    *tex;
  720.     int        bmins[2], bmaxs[2];
  721.  
  722.     mins[0] = mins[1] = 999999;
  723.     maxs[0] = maxs[1] = -99999;
  724.  
  725.     tex = s->texinfo;
  726.     
  727.     for (i=0 ; i<s->numedges ; i++)
  728.     {
  729.         e = loadmodel->surfedges[s->firstedge+i];
  730.         if (e >= 0)
  731.             v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
  732.         else
  733.             v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
  734.         
  735.         for (j=0 ; j<2 ; j++)
  736.         {
  737.             val = v->position[0] * tex->vecs[j][0] + 
  738.                 v->position[1] * tex->vecs[j][1] +
  739.                 v->position[2] * tex->vecs[j][2] +
  740.                 tex->vecs[j][3];
  741.             if (val < mins[j])
  742.                 mins[j] = val;
  743.             if (val > maxs[j])
  744.                 maxs[j] = val;
  745.         }
  746.     }
  747.  
  748.     for (i=0 ; i<2 ; i++)
  749.     {    
  750.         bmins[i] = floor(mins[i]/16);
  751.         bmaxs[i] = ceil(maxs[i]/16);
  752.  
  753.         s->texturemins[i] = bmins[i] * 16;
  754.         s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
  755.         if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
  756.             Sys_Error ("Bad surface extents");
  757.     }
  758. }
  759.  
  760.  
  761. /*
  762. =================
  763. Mod_LoadFaces
  764. =================
  765. */
  766. void Mod_LoadFaces (lump_t *l)
  767. {
  768.     dface_t        *in;
  769.     msurface_t     *out;
  770.     int            i, count, surfnum;
  771.     int            planenum, side;
  772.  
  773.     in = (void *)(mod_base + l->fileofs);
  774.     if (l->filelen % sizeof(*in))
  775.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  776.     count = l->filelen / sizeof(*in);
  777.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  778.  
  779.     loadmodel->surfaces = out;
  780.     loadmodel->numsurfaces = count;
  781.  
  782.     for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
  783.     {
  784.         out->firstedge = LittleLong(in->firstedge);
  785.         out->numedges = LittleShort(in->numedges);        
  786.         out->flags = 0;
  787.  
  788.         planenum = LittleShort(in->planenum);
  789.         side = LittleShort(in->side);
  790.         if (side)
  791.             out->flags |= SURF_PLANEBACK;            
  792.  
  793.         out->plane = loadmodel->planes + planenum;
  794.  
  795.         out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
  796.  
  797.         CalcSurfaceExtents (out);
  798.                 
  799.     // lighting info
  800.  
  801.         for (i=0 ; i<MAXLIGHTMAPS ; i++)
  802.             out->styles[i] = in->styles[i];
  803.         i = LittleLong(in->lightofs);
  804.         if (i == -1)
  805.             out->samples = NULL;
  806.         else
  807.             out->samples = loadmodel->lightdata + i;
  808.         
  809.     // set the drawing flags flag
  810.         
  811.         if (!Q_strncmp(out->texinfo->texture->name,"sky",3))    // sky
  812.         {
  813.             out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
  814.             continue;
  815.         }
  816.         
  817.         if (!Q_strncmp(out->texinfo->texture->name,"*",1))        // turbulent
  818.         {
  819.             out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
  820.             for (i=0 ; i<2 ; i++)
  821.             {
  822.                 out->extents[i] = 16384;
  823.                 out->texturemins[i] = -8192;
  824.             }
  825.             continue;
  826.         }
  827.     }
  828. }
  829.  
  830.  
  831. /*
  832. =================
  833. Mod_SetParent
  834. =================
  835. */
  836. void Mod_SetParent (mnode_t *node, mnode_t *parent)
  837. {
  838.     node->parent = parent;
  839.     if (node->contents < 0)
  840.         return;
  841.     Mod_SetParent (node->children[0], node);
  842.     Mod_SetParent (node->children[1], node);
  843. }
  844.  
  845. /*
  846. =================
  847. Mod_LoadNodes
  848. =================
  849. */
  850. void Mod_LoadNodes (lump_t *l)
  851. {
  852.     int            i, j, count, p;
  853.     dnode_t        *in;
  854.     mnode_t     *out;
  855.  
  856.     in = (void *)(mod_base + l->fileofs);
  857.     if (l->filelen % sizeof(*in))
  858.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  859.     count = l->filelen / sizeof(*in);
  860.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  861.  
  862.     loadmodel->nodes = out;
  863.     loadmodel->numnodes = count;
  864.  
  865.     for ( i=0 ; i<count ; i++, in++, out++)
  866.     {
  867.         for (j=0 ; j<3 ; j++)
  868.         {
  869.             out->minmaxs[j] = LittleShort (in->mins[j]);
  870.             out->minmaxs[3+j] = LittleShort (in->maxs[j]);
  871.         }
  872.     
  873.         p = LittleLong(in->planenum);
  874.         out->plane = loadmodel->planes + p;
  875.  
  876.         out->firstsurface = LittleShort (in->firstface);
  877.         out->numsurfaces = LittleShort (in->numfaces);
  878.         
  879.         for (j=0 ; j<2 ; j++)
  880.         {
  881.             p = LittleShort (in->children[j]);
  882.             if (p >= 0)
  883.                 out->children[j] = loadmodel->nodes + p;
  884.             else
  885.                 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
  886.         }
  887.     }
  888.     
  889.     Mod_SetParent (loadmodel->nodes, NULL);    // sets nodes and leafs
  890. }
  891.  
  892. /*
  893. =================
  894. Mod_LoadLeafs
  895. =================
  896. */
  897. void Mod_LoadLeafs (lump_t *l)
  898. {
  899.     dleaf_t     *in;
  900.     mleaf_t     *out;
  901.     int            i, j, count, p;
  902.  
  903.     in = (void *)(mod_base + l->fileofs);
  904.     if (l->filelen % sizeof(*in))
  905.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  906.     count = l->filelen / sizeof(*in);
  907.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  908.  
  909.     loadmodel->leafs = out;
  910.     loadmodel->numleafs = count;
  911.  
  912.     for ( i=0 ; i<count ; i++, in++, out++)
  913.     {
  914.         for (j=0 ; j<3 ; j++)
  915.         {
  916.             out->minmaxs[j] = LittleShort (in->mins[j]);
  917.             out->minmaxs[3+j] = LittleShort (in->maxs[j]);
  918.         }
  919.  
  920.         p = LittleLong(in->contents);
  921.         out->contents = p;
  922.  
  923.         out->firstmarksurface = loadmodel->marksurfaces +
  924.             LittleShort(in->firstmarksurface);
  925.         out->nummarksurfaces = LittleShort(in->nummarksurfaces);
  926.         
  927.         p = LittleLong(in->visofs);
  928.         if (p == -1)
  929.             out->compressed_vis = NULL;
  930.         else
  931.             out->compressed_vis = loadmodel->visdata + p;
  932.         out->efrags = NULL;
  933.         
  934.         for (j=0 ; j<4 ; j++)
  935.             out->ambient_sound_level[j] = in->ambient_level[j];
  936.     }    
  937. }
  938.  
  939. /*
  940. =================
  941. Mod_LoadClipnodes
  942. =================
  943. */
  944. void Mod_LoadClipnodes (lump_t *l)
  945. {
  946.     dclipnode_t *in, *out;
  947.     int            i, count;
  948.     hull_t        *hull;
  949.  
  950.     in = (void *)(mod_base + l->fileofs);
  951.     if (l->filelen % sizeof(*in))
  952.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  953.     count = l->filelen / sizeof(*in);
  954.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  955.  
  956.     loadmodel->clipnodes = out;
  957.     loadmodel->numclipnodes = count;
  958.  
  959.     hull = &loadmodel->hulls[1];
  960.     hull->clipnodes = out;
  961.     hull->firstclipnode = 0;
  962.     hull->lastclipnode = count-1;
  963.     hull->planes = loadmodel->planes;
  964.     hull->clip_mins[0] = -16;
  965.     hull->clip_mins[1] = -16;
  966.     hull->clip_mins[2] = -24;
  967.     hull->clip_maxs[0] = 16;
  968.     hull->clip_maxs[1] = 16;
  969.     hull->clip_maxs[2] = 32;
  970.  
  971.     hull = &loadmodel->hulls[2];
  972.     hull->clipnodes = out;
  973.     hull->firstclipnode = 0;
  974.     hull->lastclipnode = count-1;
  975.     hull->planes = loadmodel->planes;
  976.     hull->clip_mins[0] = -32;
  977.     hull->clip_mins[1] = -32;
  978.     hull->clip_mins[2] = -24;
  979.     hull->clip_maxs[0] = 32;
  980.     hull->clip_maxs[1] = 32;
  981.     hull->clip_maxs[2] = 64;
  982.  
  983.     for (i=0 ; i<count ; i++, out++, in++)
  984.     {
  985.         out->planenum = LittleLong(in->planenum);
  986.         out->children[0] = LittleShort(in->children[0]);
  987.         out->children[1] = LittleShort(in->children[1]);
  988.     }
  989. }
  990.  
  991. /*
  992. =================
  993. Mod_MakeHull0
  994.  
  995. Deplicate the drawing hull structure as a clipping hull
  996. =================
  997. */
  998. void Mod_MakeHull0 (void)
  999. {
  1000.     mnode_t        *in, *child;
  1001.     dclipnode_t *out;
  1002.     int            i, j, count;
  1003.     hull_t        *hull;
  1004.     
  1005.     hull = &loadmodel->hulls[0];    
  1006.     
  1007.     in = loadmodel->nodes;
  1008.     count = loadmodel->numnodes;
  1009.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  1010.  
  1011.     hull->clipnodes = out;
  1012.     hull->firstclipnode = 0;
  1013.     hull->lastclipnode = count-1;
  1014.     hull->planes = loadmodel->planes;
  1015.  
  1016.     for (i=0 ; i<count ; i++, out++, in++)
  1017.     {
  1018.         out->planenum = in->plane - loadmodel->planes;
  1019.         for (j=0 ; j<2 ; j++)
  1020.         {
  1021.             child = in->children[j];
  1022.             if (child->contents < 0)
  1023.                 out->children[j] = child->contents;
  1024.             else
  1025.                 out->children[j] = child - loadmodel->nodes;
  1026.         }
  1027.     }
  1028. }
  1029.  
  1030. /*
  1031. =================
  1032. Mod_LoadMarksurfaces
  1033. =================
  1034. */
  1035. void Mod_LoadMarksurfaces (lump_t *l)
  1036. {    
  1037.     int        i, j, count;
  1038.     short        *in;
  1039.     msurface_t **out;
  1040.     
  1041.     in = (void *)(mod_base + l->fileofs);
  1042.     if (l->filelen % sizeof(*in))
  1043.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  1044.     count = l->filelen / sizeof(*in);
  1045.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  1046.  
  1047.     loadmodel->marksurfaces = out;
  1048.     loadmodel->nummarksurfaces = count;
  1049.  
  1050.     for ( i=0 ; i<count ; i++)
  1051.     {
  1052.         j = LittleShort(in[i]);
  1053.         if (j >= loadmodel->numsurfaces)
  1054.             Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
  1055.         out[i] = loadmodel->surfaces + j;
  1056.     }
  1057. }
  1058.  
  1059. /*
  1060. =================
  1061. Mod_LoadSurfedges
  1062. =================
  1063. */
  1064. void Mod_LoadSurfedges (lump_t *l)
  1065. {    
  1066.     int        i, count;
  1067.     int        *in, *out;
  1068.     
  1069.     in = (void *)(mod_base + l->fileofs);
  1070.     if (l->filelen % sizeof(*in))
  1071.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  1072.     count = l->filelen / sizeof(*in);
  1073.     out = Hunk_AllocName ( count*sizeof(*out), loadname);    
  1074.  
  1075.     loadmodel->surfedges = out;
  1076.     loadmodel->numsurfedges = count;
  1077.  
  1078.     for ( i=0 ; i<count ; i++)
  1079.         out[i] = LittleLong (in[i]);
  1080. }
  1081.  
  1082. /*
  1083. =================
  1084. Mod_LoadPlanes
  1085. =================
  1086. */
  1087. void Mod_LoadPlanes (lump_t *l)
  1088. {
  1089.     int            i, j;
  1090.     mplane_t    *out;
  1091.     dplane_t     *in;
  1092.     int            count;
  1093.     int            bits;
  1094.     
  1095.     in = (void *)(mod_base + l->fileofs);
  1096.     if (l->filelen % sizeof(*in))
  1097.         Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  1098.     count = l->filelen / sizeof(*in);
  1099.     out = Hunk_AllocName ( count*2*sizeof(*out), loadname);    
  1100.     
  1101.     loadmodel->planes = out;
  1102.     loadmodel->numplanes = count;
  1103.  
  1104.     for ( i=0 ; i<count ; i++, in++, out++)
  1105.     {
  1106.         bits = 0;
  1107.         for (j=0 ; j<3 ; j++)
  1108.         {
  1109.             out->normal[j] = LittleFloat (in->normal[j]);
  1110.             if (out->normal[j] < 0)
  1111.                 bits |= 1<<j;
  1112.         }
  1113.  
  1114.         out->dist = LittleFloat (in->dist);
  1115.         out->type = LittleLong (in->type);
  1116.         out->signbits = bits;
  1117.     }
  1118. }
  1119.  
  1120. /*
  1121. =================
  1122. RadiusFromBounds
  1123. =================
  1124. */
  1125. float RadiusFromBounds (vec3_t mins, vec3_t maxs)
  1126. {
  1127.     int        i;
  1128.     vec3_t    corner;
  1129.  
  1130.     for (i=0 ; i<3 ; i++)
  1131.     {
  1132.         corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
  1133.     }
  1134.  
  1135.     return Length (corner);
  1136. }
  1137.  
  1138. /*
  1139. =================
  1140. Mod_LoadBrushModel
  1141. =================
  1142. */
  1143. void Mod_LoadBrushModel (model_t *mod, void *buffer)
  1144. {
  1145.     int            i, j;
  1146.     dheader_t    *header;
  1147.     dmodel_t     *bm;
  1148.     
  1149.     loadmodel->type = mod_brush;
  1150.     
  1151.     header = (dheader_t *)buffer;
  1152.  
  1153.     i = LittleLong (header->version);
  1154.     if (i != BSPVERSION)
  1155.         Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
  1156.  
  1157. // swap all the lumps
  1158.     mod_base = (byte *)header;
  1159.  
  1160.     for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
  1161.         ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
  1162.  
  1163. // load into heap
  1164.     
  1165.     Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
  1166.     Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
  1167.     Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
  1168.     Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
  1169.     Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
  1170.     Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
  1171.     Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
  1172.     Mod_LoadFaces (&header->lumps[LUMP_FACES]);
  1173.     Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
  1174.     Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
  1175.     Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
  1176.     Mod_LoadNodes (&header->lumps[LUMP_NODES]);
  1177.     Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
  1178.     Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
  1179.     Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
  1180.  
  1181.     Mod_MakeHull0 ();
  1182.     
  1183.     mod->numframes = 2;        // regular and alternate animation
  1184.     mod->flags = 0;
  1185.     
  1186. //
  1187. // set up the submodels (FIXME: this is confusing)
  1188. //
  1189.     for (i=0 ; i<mod->numsubmodels ; i++)
  1190.     {
  1191.         bm = &mod->submodels[i];
  1192.  
  1193.         mod->hulls[0].firstclipnode = bm->headnode[0];
  1194.         for (j=1 ; j<MAX_MAP_HULLS ; j++)
  1195.         {
  1196.             mod->hulls[j].firstclipnode = bm->headnode[j];
  1197.             mod->hulls[j].lastclipnode = mod->numclipnodes-1;
  1198.         }
  1199.         
  1200.         mod->firstmodelsurface = bm->firstface;
  1201.         mod->nummodelsurfaces = bm->numfaces;
  1202.         
  1203.         VectorCopy (bm->maxs, mod->maxs);
  1204.         VectorCopy (bm->mins, mod->mins);
  1205.         mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
  1206.         
  1207.         mod->numleafs = bm->visleafs;
  1208.  
  1209.         if (i < mod->numsubmodels-1)
  1210.         {    // duplicate the basic information
  1211.             char    name[10];
  1212.  
  1213.             sprintf (name, "*%i", i+1);
  1214.             loadmodel = Mod_FindName (name);
  1215.             *loadmodel = *mod;
  1216.             strcpy (loadmodel->name, name);
  1217.             mod = loadmodel;
  1218.         }
  1219.     }
  1220. }
  1221.  
  1222. /*
  1223. ==============================================================================
  1224.  
  1225. ALIAS MODELS
  1226.  
  1227. ==============================================================================
  1228. */
  1229.  
  1230. /*
  1231. =================
  1232. Mod_LoadAliasFrame
  1233. =================
  1234. */
  1235. void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv,
  1236.     trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
  1237. {
  1238.     trivertx_t        *pframe, *pinframe;
  1239.     int                i, j;
  1240.     daliasframe_t    *pdaliasframe;
  1241.  
  1242.     pdaliasframe = (daliasframe_t *)pin;
  1243.  
  1244.     strcpy (name, pdaliasframe->name);
  1245.  
  1246.     for (i=0 ; i<3 ; i++)
  1247.     {
  1248.     // these are byte values, so we don't have to worry about
  1249.     // endianness
  1250.         pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
  1251.         pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
  1252.     }
  1253.  
  1254.     pinframe = (trivertx_t *)(pdaliasframe + 1);
  1255.     pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname);
  1256.  
  1257.     *pframeindex = (byte *)pframe - (byte *)pheader;
  1258.  
  1259.     for (j=0 ; j<numv ; j++)
  1260.     {
  1261.         int        k;
  1262.  
  1263.     // these are all byte values, so no need to deal with endianness
  1264.         pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
  1265.  
  1266.         for (k=0 ; k<3 ; k++)
  1267.         {
  1268.             pframe[j].v[k] = pinframe[j].v[k];
  1269.         }
  1270.     }
  1271.  
  1272.     pinframe += numv;
  1273.  
  1274.     return (void *)pinframe;
  1275. }
  1276.  
  1277.  
  1278. /*
  1279. =================
  1280. Mod_LoadAliasGroup
  1281. =================
  1282. */
  1283. void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
  1284.     trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
  1285. {
  1286.     daliasgroup_t        *pingroup;
  1287.     maliasgroup_t        *paliasgroup;
  1288.     int                    i, numframes;
  1289.     daliasinterval_t    *pin_intervals;
  1290.     float                *poutintervals;
  1291.     void                *ptemp;
  1292.     
  1293.     pingroup = (daliasgroup_t *)pin;
  1294.  
  1295.     numframes = LittleLong (pingroup->numframes);
  1296.  
  1297.     paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) +
  1298.             (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname);
  1299.  
  1300.     paliasgroup->numframes = numframes;
  1301.  
  1302.     for (i=0 ; i<3 ; i++)
  1303.     {
  1304.     // these are byte values, so we don't have to worry about endianness
  1305.         pbboxmin->v[i] = pingroup->bboxmin.v[i];
  1306.         pbboxmax->v[i] = pingroup->bboxmax.v[i];
  1307.     }
  1308.  
  1309.     *pframeindex = (byte *)paliasgroup - (byte *)pheader;
  1310.  
  1311.     pin_intervals = (daliasinterval_t *)(pingroup + 1);
  1312.  
  1313.     poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
  1314.  
  1315.     paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
  1316.  
  1317.     for (i=0 ; i<numframes ; i++)
  1318.     {
  1319.         *poutintervals = LittleFloat (pin_intervals->interval);
  1320.         if (*poutintervals <= 0.0)
  1321.             Sys_Error ("Mod_LoadAliasGroup: interval<=0");
  1322.  
  1323.         poutintervals++;
  1324.         pin_intervals++;
  1325.     }
  1326.  
  1327.     ptemp = (void *)pin_intervals;
  1328.  
  1329.     for (i=0 ; i<numframes ; i++)
  1330.     {
  1331.         ptemp = Mod_LoadAliasFrame (ptemp,
  1332.                                     &paliasgroup->frames[i].frame,
  1333.                                     numv,
  1334.                                     &paliasgroup->frames[i].bboxmin,
  1335.                                     &paliasgroup->frames[i].bboxmax,
  1336.                                     pheader, name);
  1337.     }
  1338.  
  1339.     return ptemp;
  1340. }
  1341.  
  1342.  
  1343. /*
  1344. =================
  1345. Mod_LoadAliasSkin
  1346. =================
  1347. */
  1348. void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize,
  1349.     aliashdr_t *pheader)
  1350. {
  1351.     int        i;
  1352.     byte    *pskin, *pinskin;
  1353.     unsigned short    *pusskin;
  1354.  
  1355.     pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname);
  1356.     pinskin = (byte *)pin;
  1357.     *pskinindex = (byte *)pskin - (byte *)pheader;
  1358.  
  1359.     if (r_pixbytes == 1)
  1360.     {
  1361.         Q_memcpy (pskin, pinskin, skinsize);
  1362.     }
  1363.     else if (r_pixbytes == 2)
  1364.     {
  1365.         pusskin = (unsigned short *)pskin;
  1366.  
  1367.         for (i=0 ; i<skinsize ; i++)
  1368.             pusskin[i] = d_8to16table[pinskin[i]];
  1369.     }
  1370.     else
  1371.     {
  1372.         Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
  1373.                  r_pixbytes);
  1374.     }
  1375.  
  1376.     pinskin += skinsize;
  1377.  
  1378.     return ((void *)pinskin);
  1379. }
  1380.  
  1381.  
  1382. /*
  1383. =================
  1384. Mod_LoadAliasSkinGroup
  1385. =================
  1386. */
  1387. void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
  1388.     aliashdr_t *pheader)
  1389. {
  1390.     daliasskingroup_t        *pinskingroup;
  1391.     maliasskingroup_t        *paliasskingroup;
  1392.     int                        i, numskins;
  1393.     daliasskininterval_t    *pinskinintervals;
  1394.     float                    *poutskinintervals;
  1395.     void                    *ptemp;
  1396.  
  1397.     pinskingroup = (daliasskingroup_t *)pin;
  1398.  
  1399.     numskins = LittleLong (pinskingroup->numskins);
  1400.  
  1401.     paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) +
  1402.             (numskins - 1) * sizeof (paliasskingroup->skindescs[0]),
  1403.             loadname);
  1404.  
  1405.     paliasskingroup->numskins = numskins;
  1406.  
  1407.     *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
  1408.  
  1409.     pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
  1410.  
  1411.     poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname);
  1412.  
  1413.     paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
  1414.  
  1415.     for (i=0 ; i<numskins ; i++)
  1416.     {
  1417.         *poutskinintervals = LittleFloat (pinskinintervals->interval);
  1418.         if (*poutskinintervals <= 0)
  1419.             Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0");
  1420.  
  1421.         poutskinintervals++;
  1422.         pinskinintervals++;
  1423.     }
  1424.  
  1425.     ptemp = (void *)pinskinintervals;
  1426.  
  1427.     for (i=0 ; i<numskins ; i++)
  1428.     {
  1429.         ptemp = Mod_LoadAliasSkin (ptemp,
  1430.                 &paliasskingroup->skindescs[i].skin, skinsize, pheader);
  1431.     }
  1432.  
  1433.     return ptemp;
  1434. }
  1435.  
  1436.  
  1437. /*
  1438. =================
  1439. Mod_LoadAliasModel
  1440. =================
  1441. */
  1442. void Mod_LoadAliasModel (model_t *mod, void *buffer)
  1443. {
  1444.     int                    i;
  1445.     mdl_t                *pmodel, *pinmodel;
  1446.     stvert_t            *pstverts, *pinstverts;
  1447.     aliashdr_t            *pheader;
  1448.     mtriangle_t            *ptri;
  1449.     dtriangle_t            *pintriangles;
  1450.     int                    version, numframes, numskins;
  1451.     int                    size;
  1452.     daliasframetype_t    *pframetype;
  1453.     daliasskintype_t    *pskintype;
  1454.     maliasskindesc_t    *pskindesc;
  1455.     int                    skinsize;
  1456.     int                    start, end, total;
  1457.     
  1458.     start = Hunk_LowMark ();
  1459.  
  1460.     pinmodel = (mdl_t *)buffer;
  1461.  
  1462.     version = LittleLong (pinmodel->version);
  1463.     if (version != ALIAS_VERSION)
  1464.         Sys_Error ("%s has wrong version number (%i should be %i)",
  1465.                  mod->name, version, ALIAS_VERSION);
  1466.  
  1467. //
  1468. // allocate space for a working header, plus all the data except the frames,
  1469. // skin and group info
  1470. //
  1471.     size =     sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) *
  1472.              sizeof (pheader->frames[0]) +
  1473.             sizeof (mdl_t) +
  1474.             LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
  1475.             LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
  1476.  
  1477.     pheader = Hunk_AllocName (size, loadname);
  1478.     pmodel = (mdl_t *) ((byte *)&pheader[1] +
  1479.             (LittleLong (pinmodel->numframes) - 1) *
  1480.              sizeof (pheader->frames[0]));
  1481.     
  1482. //    mod->cache.data = pheader;
  1483.     mod->flags = LittleLong (pinmodel->flags);
  1484.  
  1485. //
  1486. // endian-adjust and copy the data, starting with the alias model header
  1487. //
  1488.     pmodel->boundingradius = LittleFloat (pinmodel->boundingradius);
  1489.     pmodel->numskins = LittleLong (pinmodel->numskins);
  1490.     pmodel->skinwidth = LittleLong (pinmodel->skinwidth);
  1491.     pmodel->skinheight = LittleLong (pinmodel->skinheight);
  1492.  
  1493.     if (pmodel->skinheight > MAX_LBM_HEIGHT)
  1494.         Sys_Error ("model %s has a skin taller than %d", mod->name,
  1495.                    MAX_LBM_HEIGHT);
  1496.  
  1497.     pmodel->numverts = LittleLong (pinmodel->numverts);
  1498.  
  1499.     if (pmodel->numverts <= 0)
  1500.         Sys_Error ("model %s has no vertices", mod->name);
  1501.  
  1502.     if (pmodel->numverts > MAXALIASVERTS)
  1503.         Sys_Error ("model %s has too many vertices", mod->name);
  1504.  
  1505.     pmodel->numtris = LittleLong (pinmodel->numtris);
  1506.  
  1507.     if (pmodel->numtris <= 0)
  1508.         Sys_Error ("model %s has no triangles", mod->name);
  1509.  
  1510.     pmodel->numframes = LittleLong (pinmodel->numframes);
  1511.     pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
  1512.     mod->synctype = LittleLong (pinmodel->synctype);
  1513.     mod->numframes = pmodel->numframes;
  1514.  
  1515.     for (i=0 ; i<3 ; i++)
  1516.     {
  1517.         pmodel->scale[i] = LittleFloat (pinmodel->scale[i]);
  1518.         pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
  1519.         pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
  1520.     }
  1521.  
  1522.     numskins = pmodel->numskins;
  1523.     numframes = pmodel->numframes;
  1524.  
  1525.     if (pmodel->skinwidth & 0x03)
  1526.         Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4");
  1527.  
  1528.     pheader->model = (byte *)pmodel - (byte *)pheader;
  1529.  
  1530. //
  1531. // load the skins
  1532. //
  1533.     skinsize = pmodel->skinheight * pmodel->skinwidth;
  1534.  
  1535.     if (numskins < 1)
  1536.         Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
  1537.  
  1538.     pskintype = (daliasskintype_t *)&pinmodel[1];
  1539.  
  1540.     pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
  1541.                                 loadname);
  1542.  
  1543.     pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
  1544.  
  1545.     for (i=0 ; i<numskins ; i++)
  1546.     {
  1547.         aliasskintype_t    skintype;
  1548.  
  1549.         skintype = LittleLong (pskintype->type);
  1550.         pskindesc[i].type = skintype;
  1551.  
  1552.         if (skintype == ALIAS_SKIN_SINGLE)
  1553.         {
  1554.             pskintype = (daliasskintype_t *)
  1555.                     Mod_LoadAliasSkin (pskintype + 1,
  1556.                                        &pskindesc[i].skin,
  1557.                                        skinsize, pheader);
  1558.         }
  1559.         else
  1560.         {
  1561.             pskintype = (daliasskintype_t *)
  1562.                     Mod_LoadAliasSkinGroup (pskintype + 1,
  1563.                                             &pskindesc[i].skin,
  1564.                                             skinsize, pheader);
  1565.         }
  1566.     }
  1567.  
  1568. //
  1569. // set base s and t vertices
  1570. //
  1571.     pstverts = (stvert_t *)&pmodel[1];
  1572.     pinstverts = (stvert_t *)pskintype;
  1573.  
  1574.     pheader->stverts = (byte *)pstverts - (byte *)pheader;
  1575.  
  1576.     for (i=0 ; i<pmodel->numverts ; i++)
  1577.     {
  1578.         pstverts[i].onseam = LittleLong (pinstverts[i].onseam);
  1579.     // put s and t in 16.16 format
  1580.         pstverts[i].s = LittleLong (pinstverts[i].s) << 16;
  1581.         pstverts[i].t = LittleLong (pinstverts[i].t) << 16;
  1582.     }
  1583.  
  1584. //
  1585. // set up the triangles
  1586. //
  1587.     ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
  1588.     pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
  1589.  
  1590.     pheader->triangles = (byte *)ptri - (byte *)pheader;
  1591.  
  1592.     for (i=0 ; i<pmodel->numtris ; i++)
  1593.     {
  1594.         int        j;
  1595.  
  1596.         ptri[i].facesfront = LittleLong (pintriangles[i].facesfront);
  1597.  
  1598.         for (j=0 ; j<3 ; j++)
  1599.         {
  1600.             ptri[i].vertindex[j] =
  1601.                     LittleLong (pintriangles[i].vertindex[j]);
  1602.         }
  1603.     }
  1604.  
  1605. //
  1606. // load the frames
  1607. //
  1608.     if (numframes < 1)
  1609.         Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
  1610.  
  1611.     pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
  1612.  
  1613.     for (i=0 ; i<numframes ; i++)
  1614.     {
  1615.         aliasframetype_t    frametype;
  1616.  
  1617.         frametype = LittleLong (pframetype->type);
  1618.         pheader->frames[i].type = frametype;
  1619.  
  1620.         if (frametype == ALIAS_SINGLE)
  1621.         {
  1622.             pframetype = (daliasframetype_t *)
  1623.                     Mod_LoadAliasFrame (pframetype + 1,
  1624.                                         &pheader->frames[i].frame,
  1625.                                         pmodel->numverts,
  1626.                                         &pheader->frames[i].bboxmin,
  1627.                                         &pheader->frames[i].bboxmax,
  1628.                                         pheader, pheader->frames[i].name);
  1629.         }
  1630.         else
  1631.         {
  1632.             pframetype = (daliasframetype_t *)
  1633.                     Mod_LoadAliasGroup (pframetype + 1,
  1634.                                         &pheader->frames[i].frame,
  1635.                                         pmodel->numverts,
  1636.                                         &pheader->frames[i].bboxmin,
  1637.                                         &pheader->frames[i].bboxmax,
  1638.                                         pheader, pheader->frames[i].name);
  1639.         }
  1640.     }
  1641.  
  1642.     mod->type = mod_alias;
  1643.  
  1644. // FIXME: do this right
  1645.     mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
  1646.     mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
  1647.  
  1648. //
  1649. // move the complete, relocatable alias model to the cache
  1650. //    
  1651.     end = Hunk_LowMark ();
  1652.     total = end - start;
  1653.     
  1654.     Cache_Alloc (&mod->cache, total, loadname);
  1655.     if (!mod->cache.data)
  1656.         return;
  1657.     memcpy (mod->cache.data, pheader, total);
  1658.  
  1659.     Hunk_FreeToLowMark (start);
  1660. }
  1661.  
  1662. //=============================================================================
  1663.  
  1664. /*
  1665. =================
  1666. Mod_LoadSpriteFrame
  1667. =================
  1668. */
  1669. void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe)
  1670. {
  1671.     dspriteframe_t        *pinframe;
  1672.     mspriteframe_t        *pspriteframe;
  1673.     int                    i, width, height, size, origin[2];
  1674.     unsigned short        *ppixout;
  1675.     byte                *ppixin;
  1676.  
  1677.     pinframe = (dspriteframe_t *)pin;
  1678.  
  1679.     width = LittleLong (pinframe->width);
  1680.     height = LittleLong (pinframe->height);
  1681.     size = width * height;
  1682.  
  1683.     pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes,
  1684.                                    loadname);
  1685.  
  1686.     Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size);
  1687.     *ppframe = pspriteframe;
  1688.  
  1689.     pspriteframe->width = width;
  1690.     pspriteframe->height = height;
  1691.     origin[0] = LittleLong (pinframe->origin[0]);
  1692.     origin[1] = LittleLong (pinframe->origin[1]);
  1693.  
  1694.     pspriteframe->up = origin[1];
  1695.     pspriteframe->down = origin[1] - height;
  1696.     pspriteframe->left = origin[0];
  1697.     pspriteframe->right = width + origin[0];
  1698.  
  1699.     if (r_pixbytes == 1)
  1700.     {
  1701.         Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
  1702.     }
  1703.     else if (r_pixbytes == 2)
  1704.     {
  1705.         ppixin = (byte *)(pinframe + 1);
  1706.         ppixout = (unsigned short *)&pspriteframe->pixels[0];
  1707.  
  1708.         for (i=0 ; i<size ; i++)
  1709.             ppixout[i] = d_8to16table[ppixin[i]];
  1710.     }
  1711.     else
  1712.     {
  1713.         Sys_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
  1714.                  r_pixbytes);
  1715.     }
  1716.  
  1717.     return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
  1718. }
  1719.  
  1720.  
  1721. /*
  1722. =================
  1723. Mod_LoadSpriteGroup
  1724. =================
  1725. */
  1726. void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
  1727. {
  1728.     dspritegroup_t        *pingroup;
  1729.     mspritegroup_t        *pspritegroup;
  1730.     int                    i, numframes;
  1731.     dspriteinterval_t    *pin_intervals;
  1732.     float                *poutintervals;
  1733.     void                *ptemp;
  1734.  
  1735.     pingroup = (dspritegroup_t *)pin;
  1736.  
  1737.     numframes = LittleLong (pingroup->numframes);
  1738.  
  1739.     pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
  1740.                 (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
  1741.  
  1742.     pspritegroup->numframes = numframes;
  1743.  
  1744.     *ppframe = (mspriteframe_t *)pspritegroup;
  1745.  
  1746.     pin_intervals = (dspriteinterval_t *)(pingroup + 1);
  1747.  
  1748.     poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
  1749.  
  1750.     pspritegroup->intervals = poutintervals;
  1751.  
  1752.     for (i=0 ; i<numframes ; i++)
  1753.     {
  1754.         *poutintervals = LittleFloat (pin_intervals->interval);
  1755.         if (*poutintervals <= 0.0)
  1756.             Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
  1757.  
  1758.         poutintervals++;
  1759.         pin_intervals++;
  1760.     }
  1761.  
  1762.     ptemp = (void *)pin_intervals;
  1763.  
  1764.     for (i=0 ; i<numframes ; i++)
  1765.     {
  1766.         ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i]);
  1767.     }
  1768.  
  1769.     return ptemp;
  1770. }
  1771.  
  1772.  
  1773. /*
  1774. =================
  1775. Mod_LoadSpriteModel
  1776. =================
  1777. */
  1778. void Mod_LoadSpriteModel (model_t *mod, void *buffer)
  1779. {
  1780.     int                    i;
  1781.     int                    version;
  1782.     dsprite_t            *pin;
  1783.     msprite_t            *psprite;
  1784.     int                    numframes;
  1785.     int                    size;
  1786.     dspriteframetype_t    *pframetype;
  1787.     
  1788.     pin = (dsprite_t *)buffer;
  1789.  
  1790.     version = LittleLong (pin->version);
  1791.     if (version != SPRITE_VERSION)
  1792.         Sys_Error ("%s has wrong version number "
  1793.                  "(%i should be %i)", mod->name, version, SPRITE_VERSION);
  1794.  
  1795.     numframes = LittleLong (pin->numframes);
  1796.  
  1797.     size = sizeof (msprite_t) +    (numframes - 1) * sizeof (psprite->frames);
  1798.  
  1799.     psprite = Hunk_AllocName (size, loadname);
  1800.  
  1801.     mod->cache.data = psprite;
  1802.  
  1803.     psprite->type = LittleLong (pin->type);
  1804.     psprite->maxwidth = LittleLong (pin->width);
  1805.     psprite->maxheight = LittleLong (pin->height);
  1806.     psprite->beamlength = LittleFloat (pin->beamlength);
  1807.     mod->synctype = LittleLong (pin->synctype);
  1808.     psprite->numframes = numframes;
  1809.  
  1810.     mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
  1811.     mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
  1812.     mod->mins[2] = -psprite->maxheight/2;
  1813.     mod->maxs[2] = psprite->maxheight/2;
  1814.     
  1815. //
  1816. // load the frames
  1817. //
  1818.     if (numframes < 1)
  1819.         Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
  1820.  
  1821.     mod->numframes = numframes;
  1822.     mod->flags = 0;
  1823.  
  1824.     pframetype = (dspriteframetype_t *)(pin + 1);
  1825.  
  1826.     for (i=0 ; i<numframes ; i++)
  1827.     {
  1828.         spriteframetype_t    frametype;
  1829.  
  1830.         frametype = LittleLong (pframetype->type);
  1831.         psprite->frames[i].type = frametype;
  1832.  
  1833.         if (frametype == SPR_SINGLE)
  1834.         {
  1835.             pframetype = (dspriteframetype_t *)
  1836.                     Mod_LoadSpriteFrame (pframetype + 1,
  1837.                                          &psprite->frames[i].frameptr);
  1838.         }
  1839.         else
  1840.         {
  1841.             pframetype = (dspriteframetype_t *)
  1842.                     Mod_LoadSpriteGroup (pframetype + 1,
  1843.                                          &psprite->frames[i].frameptr);
  1844.         }
  1845.     }
  1846.  
  1847.     mod->type = mod_sprite;
  1848. }
  1849.  
  1850. //=============================================================================
  1851.  
  1852. /*
  1853. ================
  1854. Mod_Print
  1855. ================
  1856. */
  1857. void Mod_Print (void)
  1858. {
  1859.     int        i;
  1860.     model_t    *mod;
  1861.  
  1862.     Con_Printf ("Cached models:\n");
  1863.     for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
  1864.     {
  1865.         Con_Printf ("%8p : %s",mod->cache.data, mod->name);
  1866.         if (mod->needload & NL_UNREFERENCED)
  1867.             Con_Printf (" (!R)");
  1868.         if (mod->needload & NL_NEEDS_LOADED)
  1869.             Con_Printf (" (!P)");
  1870.         Con_Printf ("\n");
  1871.     }
  1872. }
  1873.  
  1874.  
  1875.